module Explode.DemoGameState;
private import Explode.Editor;
private import Explode.GameState;
private import Explode.GameTitleState;
private import Explode.GameoverState;
private import Explode.PauseMenuState;
private import Explode.Stage;
private import Explode.Player;
private import Explode.GameConfig;
private import Explode.ScoreBoard;
private import State.IState;
private import Input.KeyCode;
private import Input.GamePad;
private import Input.Mouse;
private import Input.InputRecorder;
private import Graphics.IGraphics;
private import Sound.Manager;
private import System.Console;
private import std.file;
private import std.string;
private import std.format;
private import std.random;

/**
*	タイトルデモプレイ用
**/
public class DemoGameState : GameState{
	public static const int CLEAR = 100;
	public static const int DEAD  = 200;
	protected int _returnValue = 0;
	public int returnValue(){return _returnValue;}

	protected IState _caller;
	protected GameTitleState _titleState;
	protected bool _returnFlag;
	protected PauseScrollState _scroller; 
	protected string _fileName;
	protected bool _autoDemo;

	public void autoDemo( bool v ) {
		_autoDemo = v;
	} //

	public this( GameTitleState e ,IGraphics g ) {
		super( g );
		_titleState = e;
	} //

	public IState action() {
		_frameCnt++;
		_stage.action();

		if ( _pauseFlag ) return _scroller.call( this );
		if ( _stage.mode == GameStage.MODE_DEAD ) {
			SoundManager.getSprite().play( _stage.missSound ).release();
			return _dying.call( _titleState );
		} else 
		if ( _stage.mode == GameStage.MODE_CLEAR ) {
			SoundManager.getSprite().play( _stage.goalSound ).release();
			(cast(StageClearState)_stageClear).autoDemo = _autoDemo;
			if ( _autoDemo ) 
					return _stageClear.call( this );
			else	return _stageClear.call( _titleState );
		} else
		if ( _stage.mode == GameStage.MODE_GAME ) {
			return _titleState.call( this );
		}
		if ( _returnFlag ) return _titleState.call( this );

		return this;
	} //

	public IState call( IState caller ){
		_caller = caller;
		initObject();
		
		_zoom   = 0;
		_key_dn = 0;
		_key_up = 0;
		_key_lt = 0;
		_key_rt = 0;
		_param.reset();
		_pauseFlag = false;
		_returnFlag = false;
		_gamepad.reset();
		if ( !(caller is _scroller ) ) {
			if ( !(caller is _stageClear ) )
				SoundManager.background.play( _stage.gameBgm , -1 );
			bool b = loadRandom();
			if ( ! b ) return caller.call( this );
		}

		return this;
	} //
	
	protected void initObject(){
		if ( _stage is null ) {
			_gamepad	   = new VirtualGamePad( 8 );
			_mouse		   = new BasicMouse();
			_param		   = new GameParam();
			_stage		   = new DemoGameStage( _graphics , _param );
			_stage.gamepad = _gamepad;
			_stage.mouse   = _mouse;
			_scroller	   = new PauseScrollState( this , _param , _gamepad , _graphics );
			_stageClear	   = new StageClearState( _stage , _param , _gamepad );
			_dying		   = new DyingState( _stage , _param );
			setStageNumber( GameConfig.lastStage );
		}
	} //
	
	public bool loadRandom() {
		string srcDir = GameConfig.stageDir ~"/replay/";
		string[] filestmp = listdir(srcDir);
		if ( filestmp.length < 0 ) return false;

		string[] files;
		foreach ( int i , string file ; filestmp ) {
			if ( find( file , ".txt" ) >= 0 ) {
				files ~= file;
			}
		}

		uint r = rand() % files.length;
		_fileName = srcDir ~ files[r];
		return _stage.loadStageFromFile( _fileName );
	} //
	public bool loadNext() {
		string srcDir = GameConfig.stageDir ~"/replay/";
		string[] filestmp = listdir(srcDir);
		if ( filestmp.length < 0 ) return false;

		string[] files;
		foreach ( int i , string file ; filestmp ) {
			if ( find( file , ".txt" ) >= 0 ) {
				files ~= file;
			}
		}

		string nxt = _fileName;
		foreach ( int i , string f ; files ) {
			string gs = srcDir ~ f;
			if ( gs == _fileName ) {
				nxt = srcDir ~ files[ (i+1) % files.length ];
			}
		}
		_fileName = nxt;
		return _stage.loadStageFromFile( _fileName );
	} //

	public bool onKeyDown( int keyCode ){
		_returnFlag = true;
		return true;
	} //
	public bool onMouseWheel( int x , int y , int delta) {
		if ( delta < 0 ) _stage.zoomIn();
		 else 			 _stage.zoomOut();
		return true;
	} //


	public bool onJoyAxis( int deviceId , int axis , int delta ){
		_returnFlag = true;
		return true;
	} //
	
	public bool onJoyButtonDown( int id , int button ) {
		_returnFlag = true;
		return true;
	} //
} //

public class DemoGameStage : GameStage {
	public this( IGraphics g , GameParam p ) {
		super( g , p );
	} //
	protected void initObject( IGraphics g , GameParam p ) {
		super.initObject( g , p);
		_scoreBoard = new DemoScoreBoard( this , p );
	} //
} //


public class DemoScoreBoard : ScoreBoard {
	public this( GameStage stage , GameParam param ) {
		super( stage , param );
	} //

	public bool draw( IGraphics g ) {
		float clipX  = g.viewrect.x  , clipY  = g.viewrect.y , 
			  clipX2 = g.viewrect.x2 , clipY2 = g.viewrect.y2;
		const int W=16;
		const int H=16;

		Player p  = _stage.player;
		_frameCnt = _stage.frameCnt;
		_goldCnt  = _stage.goldCnt;
		_lifeCnt  = _param.life;
		_stageNum = _param.stageNum;
		_score	  = p.score + _param.score;
		g.setViewport( 0 , 0 , W * 40 , H * 30 ); 
		int bm  = g.blendMode;
		{
			Color c;
			c.color = 0xaa000033;
			g.drawFilledRect( 0 ,  H * 28 , W * 40 , 32 , c );

			g.blendMode = g.ALPHA_ADD;
			c.color = 0xccffff00;
			
			string top2	  = format( "     %d        %03d       %s" 
									, _lifeCnt , _stageNum , _stage.cpu) ;
			string bottom  = format( "GOLD %03d   SCORE %06d   TIME %06d" , _goldCnt , _score , _frameCnt ) ;
			string bottom2 = format( "     %03d         %06d        %06d" , _goldCnt , _score , _frameCnt ) ;
			int bx = cast(int)(W * 40 - bottom.length * W ) / 2;

			g.drawText( bottom , bx  , H * 28 , c , W , H * 2 );

			g.blendMode = bm;

			c.color = ( _goldCnt > 0 ) ? 0xccffffff : 0xcc00ffff; 
			g.drawText( bottom2, bx  , H * 28 , c , W , H * 2 );
		}
		g.setViewport( clipX , clipY , clipX2 , clipY2);
		return true;
	} //

} //

